package com.hq.tomato.ms.dlq;

import com.hq.tomato.ms.context.StrategyApplication;
import com.hq.tomato.ms.strategy.DlqStrategy;
import com.rabbitmq.client.Channel;
import com.hq.tomato.ms.strategy.MongoDbDlqStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.CollectionUtils;

import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;
import java.util.Set;


/**
 *
 *
 * @Description: <br>
 * @Project: <br>
 * @CreateDate: Created in 2019-11-19 10:23 <br>
 * @Author: <a href="1026365768@qq.com">qiang.hu</a>
 */
@Slf4j
public class DispatcherDlq implements ChannelAwareMessageListener, ApplicationContextAware {
    private ApplicationContext applicationContext;

    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        try {
            String routeKey = message.getMessageProperties().getReceivedRoutingKey();
            byte[] body = message.getBody();
            String bodyStr = new String(body, StandardCharsets.UTF_8);


            Class<? extends DlqStrategy> strategy = StrategyApplication.getStrategy(routeKey);
            if(Objects.isNull(strategy)){
                log.warn("【未获取到死信队列处理策略,消息体为:{}】",bodyStr);
                return;
            }
            DlqStrategy dlqStrategy = null;
            try {
                Map<String, ? extends DlqStrategy> beansOfType = applicationContext.getBeansOfType(strategy);
                if(!CollectionUtils.isEmpty(beansOfType)){
                    if(beansOfType.size()!=1){
                        Set<String> strings = beansOfType.keySet();
                        log.warn("找到了多个bean,beanName 为:{},消息体为:{}",strings,bodyStr);
                    }else{
                        dlqStrategy = beansOfType.values().stream().findFirst().orElse(null);
                    }
                }
            }catch (Exception e){
                String unSupportMsg =  getUnSupportMsg(strategy);
                log.warn("【暂不支持此策略,提示消息:{},消息为:{}】",unSupportMsg,bodyStr);
            }

            if(Objects.isNull(dlqStrategy)){
                return;
            }

            dlqStrategy.process(message,channel);

        }catch (Exception e){
            log.warn("死信队列消费异常,异常信息为:{}",e.getMessage());
        }
    }


    private String getUnSupportMsg(Class<? extends DlqStrategy> strategy) {
        String msg = "";
        if(MongoDbDlqStrategy.class.equals(strategy)){
            msg = "请检查是否配置了MongoDb";
        }
        return msg;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
